import java.io.*;
import java.util.*;
import java.text.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.lang.*;
import java.lang.reflect.*;
import java.net.*;
import java.sql.*;
import com.sun.mail.smtp.*;
import javax.mail.*;
import javax.mail.internet.*;
import dbBean.DBConnectionManager;

public class ServletGoogleGPS extends HttpServlet {
  private DBConnectionManager connMgr;
  private TreeMap cache;
  private static final String DBNAME="mysql";
  ServletContext sc;
  String jspDir=null;

 public void getUsersList(HttpServletRequest request, HttpServletResponse response, Integer id) {
      Connection con=null;
      StringBuffer resp=new StringBuffer("<html><body>");
      try {
	String pos=null;

	response.setHeader("Cache-Control", "max-age=1, must-revalidate");
	response.setHeader("Content-Type", "text/html");

      	PrintWriter out=new PrintWriter(response.getOutputStream());

	  sc.log("- Se va a consultar la lista de usuarios en la BBDD");
          con = connMgr.getConnection("mysql");
          Statement stmt = con.createStatement();
	  ResultSet rs=stmt.executeQuery("SELECT id, user, password, digest, telefono, email, timestamp FROM usuarios ORDER BY id;");

	  resp.append("<table><tr><td><b>id</b></td><td><b>user</b></td><td><b>password</b></td><td><b>digest</b></td><td><b>telefono</b></td><td><b>email</b></td><td><b>timestamp</b></td></tr>");
	  while(rs.next()) {
		resp.append("<tr><td>"+rs.getString(1)+"</td>");
		resp.append("<td>"+rs.getString(2)+"</td>");
		resp.append("<td>"+rs.getString(3)+"</td>");
		resp.append("<td>"+rs.getString(4)+"</td>");
		resp.append("<td>"+rs.getString(5)+"</td>");
		resp.append("<td>"+rs.getString(6)+"</td>");
		resp.append("<td>"+rs.getString(7)+"</td></tr>");

	  }
	  resp.append("</table>");
	  resp.append("</body></html>");
	  out.write(resp.toString());

	  rs.close();
	  stmt.close();
	  sc.log("- Se han obtenido la lista de usuarios correctamente");
	out.close();
	
      } catch (SQLException e) {
	sc.log("getUsersList",e);
	sc.log(resp.toString());
      } catch (IOException e) {
	sc.log("getUsersList",e);
      }
      if(con!=null)
	connMgr.freeConnection("mysql",con);
 }

 public void nuevoUsuario(HttpServletRequest request, HttpServletResponse response) {
      String usuario=request.getParameter("usuario");
      String password=request.getParameter("password");
      String email=request.getParameter("email");
      Connection con=null;
      String mailhost="127.0.0.1";

      try {
	if(usuario==null)
		usuario="";
	if(password==null)
		password="";
	if(email==null)
		email="";

	if((usuario.length()==0) || (password.length()==0) ||
	(email.length()==0) || (usuario.length() > 12) || 
	(password.length() > 12) || (email.length() > 255)) {
		sc.log("- WARNING: parametros incorrectos en nuevoUsuario");
		Locale locale=request.getLocale();
		ResourceBundle bundle=ResourceBundle.getBundle("messages.messages", locale);
	  	request.setAttribute("msg", bundle.getString("msg.1"));
	  	request.setAttribute("next","/VEGPS/jsp/NuevoUsuario.jsp");
		RequestDispatcher rd=sc.getRequestDispatcher("/jsp/msg.jsp");
		rd.forward(request,response);
        } else {
	  usuario=usuario.trim();
	  password=password.trim();
	  email=email.trim();
	  sc.log("- Se va a consultar si ya existe el usuario en la BBDD");
	  con = connMgr.getConnection("mysql");
	  PreparedStatement pstmt = con.prepareStatement("SELECT * FROM usuarios WHERE user=?;");
	  pstmt.setString(1,usuario);
	  ResultSet rs=pstmt.executeQuery();
	  if(rs.next()) {
		rs.close();
		pstmt.close();
		sc.log("- El nombre de usuario '"+usuario+"' ya existe");	
		Locale locale=request.getLocale();
		ResourceBundle bundle=ResourceBundle.getBundle("messages.messages", locale);
		request.setAttribute("msg", bundle.getString("msg.2").replace("{0}", usuario));
		request.setAttribute("next","/VEGPS/jsp/NuevoUsuario.jsp");
		RequestDispatcher rd=sc.getRequestDispatcher("/jsp/msg.jsp");
		rd.forward(request,response);
	  } else {
		rs.close();
	  	String passwordCrypt=PasswordService.getInstance().encrypt(password);
	  	String digest=PasswordService.getInstance().encrypt(usuario.toLowerCase()+"\000"+password);
	  	pstmt=con.prepareStatement("INSERT INTO usuarios (user, password, digest, email) VALUES (?, ?, ?, ?);");
		pstmt.setString(1, usuario);
		pstmt.setString(2, passwordCrypt);
		pstmt.setString(3, digest);
		pstmt.setString(4, email);
		pstmt.executeUpdate();
	  	pstmt.close();

                Properties props=System.getProperties();
                props.put("mail.smtp.host", mailhost);
                props.put("mail.smtp.auth", false);

                Session session=Session.getInstance(props, null);

                Message msg=new MimeMessage(session);
                msg.setFrom(new InternetAddress("contacto@gpsou.es"));
                msg.setRecipient(Message.RecipientType.TO, new InternetAddress(email));
                msg.setSubject("GPS-ou");

		Locale locale=request.getLocale();
		ResourceBundle bundle=ResourceBundle.getBundle("messages.messages", locale);
		String texto="<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n";
		texto+="<html>\n";
		texto+="<head>\n";
		texto+="  <title>GPSou</title>\n";
		texto+="  <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n";
		texto+="</head>\n";
		texto+="<body>\n";
		texto+="  <p style=\"text-align: center\"><img src=\"http://www.gpsou.es/VEGPS/html/images/GPSou-logo-banner.png\" alt=\"GPSou\"></p>\n";
		texto+="<div style=\"text-align: center\">\n";
		texto+="<table border=\"0\" width=\"530px\" cellspacing=\"0\" cellpadding=\"0\" style=\"margin-left: auto; margin-right: auto\">\n";
		texto+="<tr><td>\n";
		texto+="<p style=\"text-align: left\"><br>\n";
		texto+=bundle.getString("mail.1").replace("{0}", usuario);
                texto+="</p></td></tr>\n";
                texto+="</table>\n";
                texto+="</div>\n";
                texto+="</body>\n";
                texto+="</html>";

                msg.setContent(texto, "text/html");

                msg.setHeader("X-Mailer", "smtpsend");
                msg.setSentDate(new java.util.Date());

                SMTPTransport t=(SMTPTransport)session.getTransport("smtp");
                t.connect(mailhost, null, null);
                t.sendMessage(msg, msg.getAllRecipients());

                t.close();

	    	sc.log("- El usuario se ha dado de alta correctamente");
	    	RequestDispatcher rd=sc.getRequestDispatcher("/jsp/InfoAlta.jsp");
	    	rd.forward(request,response);
	  }
	
        }
      } catch (SQLException e) {
	  sc.log("nuevoUsuario",e);
      } catch (ServletException e) {
	sc.log("nuevoUsuario",e);
      } catch (IOException e) {
	sc.log("nuevoUsuario",e);
      } catch (MessagingException e) {
	sc.log("nuevoUsuario",e);
      }
      if(con!=null)
	  connMgr.freeConnection("mysql",con);
 }

  public void validar(HttpServletRequest request, HttpServletResponse response) {
      String login=request.getParameter("login");
      String password=request.getParameter("password");	
      String check=request.getParameter("check");
      String datos=request.getParameter("datos");
      int idUser=0;
      String user=null;
      Connection con=null;
      
      try {
	if(login==null)
		login="";
	if(password==null)
		password="";

	if((login.length()==0) || (password.length()==0) ||
	(login.length()) > 12 || (password.length() > 12)) {
	  sc.log("- WARNING: parametro erroneos en la validacion");
	  Locale locale=request.getLocale();
	  ResourceBundle bundle=ResourceBundle.getBundle("messages.messages", locale);
	  request.setAttribute("msg", bundle.getString("msg.3"));
	  request.setAttribute("next","/VEGPS/jsp/index.jsp");
	  RequestDispatcher rd=sc.getRequestDispatcher("/jsp/msg.jsp");
	  rd.forward(request,response);
        } else {
	  login=login.trim();
	  password=password.trim();
	  String passwdCrypt=PasswordService.getInstance().encrypt(password);
	  sc.log("- Se va a validar el usuario en la BBDD");
          con = connMgr.getConnection("mysql");
          PreparedStatement pstmt;
	  if(login.matches("\\d\\d\\d\\d\\d\\d\\d\\d\\d"))
	    pstmt=con.prepareStatement("SELECT * FROM usuarios WHERE telefono='"+login+"' AND password=?;");
	  else
	    pstmt=con.prepareStatement("SELECT * FROM usuarios WHERE user='"+login+"' AND password=?;");
	  pstmt.setString(1, passwdCrypt);
	  ResultSet rs=pstmt.executeQuery();
	  if(rs.next()) {
		if(check!=null) {
		  PrintWriter out=new PrintWriter(response.getOutputStream());
		  out.write("OK");
		  out.close();
		} else if(datos!=null) {
		  idUser=rs.getInt("id");
		  PrintWriter out=new PrintWriter(response.getOutputStream());
		  out.write(insertaBD(idUser, datos));
		  out.close();
		} else if(rs.getString("telefono")!=null) {
		  idUser=rs.getInt("id");
		  user=rs.getString("user");
		  sc.log("- El usuario se ha validado correctamente. Se crea la sesion con el identificador de usuario "+idUser);
		  HttpSession session=request.getSession(true);
		  session.setAttribute("id", new Integer(idUser));
	  	  RequestDispatcher rd=sc.getRequestDispatcher("/jsp/Principal.jsp");
	  	  rd.forward(request,response);
		} else {
	  	  Locale locale=request.getLocale();
	  	  ResourceBundle bundle=ResourceBundle.getBundle("messages.messages", locale);
	  	  request.setAttribute("msg", bundle.getString("msg.4").replace("{0}", login));
	  	  request.setAttribute("next","/VEGPS/jsp/index.jsp");
	  	  RequestDispatcher rd=sc.getRequestDispatcher("/jsp/msg.jsp");
	  	  rd.forward(request,response);
		}
	  } else {
		if(check!=null) {
		  PrintWriter out=new PrintWriter(response.getOutputStream());
		  out.write("ERROR AUTENTICACION");
		  out.close();
	        } else {
		  sc.log("- Los datos introducidos no corresponden a un usuario válido");
		  Locale locale=request.getLocale();
		  ResourceBundle bundle=ResourceBundle.getBundle("messages.messages", locale);
	  	  request.setAttribute("msg", bundle.getString("msg.5"));
	  	  request.setAttribute("next","/VEGPS/jsp/index.jsp");
	  	  RequestDispatcher rd=sc.getRequestDispatcher("/jsp/msg.jsp");
	  	  rd.forward(request,response);
		}
	  }
	  rs.close();
	  pstmt.close();

        }
      } catch (IOException e) {
	sc.log("validar",e);
      } catch (SQLException e) {
	sc.log("validar",e);
      } catch (ServletException e) {
	sc.log("validar",e);
      }
      if(con!=null)
	connMgr.freeConnection("mysql",con);
  }

  public void getRuta(HttpServletRequest request, HttpServletResponse response, Integer id) {
      String desde=request.getParameter("desde");
      String hasta=request.getParameter("hasta");	
      if(desde==null)
	desde="";
      if(hasta==null)
	hasta="";

      Timestamp desdeTs=new Timestamp(0);
      Timestamp hastaTs=new Timestamp(new java.util.Date().getTime());

      if(desde!="") {
	try {
	  desdeTs=Timestamp.valueOf(desde);
	} catch(IllegalArgumentException e) {e.printStackTrace();}
      }
      if(hasta!="") {
	try {
	  hastaTs=Timestamp.valueOf(hasta);
	} catch(IllegalArgumentException e) {e.printStackTrace();}
      }

      Connection con=null;
      try {
	response.setHeader("Cache-Control", "max-age=1, must-revalidate");

	PrintWriter out=new PrintWriter(response.getOutputStream());
	Timestamp timestamp=null;
	sc.log("- Se va a consultar la ruta en la BBDD");
        con = connMgr.getConnection("mysql");
	PreparedStatement pstmt=null;
	if((desde=="") && (hasta=="")) {
            pstmt = con.prepareStatement("SELECT timestamp, latitud, longitud, velocidad, rumbo, altitud FROM datos WHERE UserId="+id.toString()+" ORDER BY timestamp;");
	} else {
            pstmt = con.prepareStatement("SELECT timestamp, latitud, longitud, velocidad, rumbo, altitud FROM datos WHERE UserId="+id.toString()+" AND timestamp BETWEEN ? AND ? ORDER BY timestamp;");
	    pstmt.setTimestamp(1, desdeTs);
	    pstmt.setTimestamp(2, hastaTs);
	}
	ResultSet rs=pstmt.executeQuery();
	while(rs.next()) {
	    out.write("#");
	    timestamp=rs.getTimestamp(1);
	    out.write(timestamp.toString());
	    out.write(";");
	    out.write(rs.getString(2));
	    out.write(";");
	    out.write(rs.getString(3));
	    out.write(";");
	    out.write(rs.getString(4));
	    out.write(";");
	    out.write(rs.getString(5));
	    out.write(";");
	    out.write(rs.getString(6));
	}
	rs.close();
	pstmt.close();
	sc.log("- Se ha obtenido la ruta correctamente");

	out.close();
	
      } catch (SQLException e) {
	sc.log("getRuta",e);
      } catch (IOException e) {
	sc.log("getRuta",e);
      }
      if(con!=null)
	connMgr.freeConnection("mysql",con);
  }

  public void getEncodedRuta(HttpServletRequest request, HttpServletResponse response, Integer id) {
      String desde=request.getParameter("desde");
      String hasta=request.getParameter("hasta");	
      if(desde==null)
	desde="";
      if(hasta==null)
	hasta="";

      Timestamp desdeTs=new Timestamp(0);
      Timestamp hastaTs=new Timestamp(new java.util.Date().getTime());

      if(desde!="") {
	try {
	  desdeTs=Timestamp.valueOf(desde);
	} catch(IllegalArgumentException e) {e.printStackTrace();}
      }
      if(hasta!="") {
	try {
	  hastaTs=Timestamp.valueOf(hasta);
	} catch(IllegalArgumentException e) {e.printStackTrace();}
      }

      Connection con=null;
      try {
	response.setHeader("Cache-Control", "max-age=1, must-revalidate");

	PrintWriter out=new PrintWriter(response.getOutputStream());
	Timestamp timestamp=null;
	sc.log("- Se va a consultar la ruta codificada en la BBDD");
        con = connMgr.getConnection("mysql");
	PreparedStatement pstmt=null;
	if((desde=="") && (hasta=="")) {
            pstmt = con.prepareStatement("SELECT latitud, longitud FROM datos WHERE UserId="+id.toString()+" ORDER BY timestamp;");
	} else {
            pstmt = con.prepareStatement("SELECT latitud, longitud FROM datos WHERE UserId="+id.toString()+" AND timestamp BETWEEN ? AND ? ORDER BY timestamp;");
	    pstmt.setTimestamp(1, desdeTs);
	    pstmt.setTimestamp(2, hastaTs);
	}
	ResultSet rs=pstmt.executeQuery();

	int latitud, latitudAnterior=0;
	int longitud, longitudAnterior=0;
	while(rs.next()) {
	    latitud=rs.getInt(1);
	    longitud=rs.getInt(2);
	    out.write(googleEncode(latitud-latitudAnterior, longitud-longitudAnterior));
	    latitudAnterior=latitud;
	    longitudAnterior=longitud;
	
	}
	rs.close();
	pstmt.close();
	sc.log("- Se ha obtenido la ruta codificada correctamente");

	out.close();
	
      } catch (SQLException e) {
	sc.log("getEncodedRuta",e);
      } catch (IOException e) {
	sc.log("getEncodedRuta",e);
      }
      if(con!=null)
	connMgr.freeConnection("mysql",con);
  }

  String googleEncode(int lat, int lon) {
      String result="";
      int c;

      lat/=5;
      lon/=5;
      
      if(lat<0)
	lat=~lat;
      if(lon<0)
	lon=~lon;

      do {
	c=lat & 0x1F;
	lat >>= 5;
	if(lat > 0)
	  c |= 0x20;
	result+=String.valueOf((char)(c+63));
      } while(lat > 0);

      do {
	c=lon & 0x1F;
	lon >>= 5;
	if(lon > 0)
	  c |= 0x20;
	result+=String.valueOf((char)(c+63));
      } while(lon > 0);

      return(result);
  }

  public void getPos(HttpServletRequest request, HttpServletResponse response, Integer id) {
      Connection con=null;
      try {
	String pos=null;

	response.setHeader("Cache-Control", "max-age=1, must-revalidate");

      	PrintWriter out=new PrintWriter(response.getOutputStream());
	if((pos=(String)cache.get(id))!=null) {
	  sc.log("- Se ha encontrado la posicion mas reciente del id="+id+" en la cache");
	  out.write(pos);
	} else {
	  sc.log("- Se va a consultar la posicion en la BBDD");
          con = connMgr.getConnection("mysql");
          Statement stmt = con.createStatement();
//	  ResultSet rs=stmt.executeQuery("SELECT timestamp, latitud, longitud, velocidad, rumbo, altitud FROM datos WHERE UserId="+id.toString()+";");
	  ResultSet rs=stmt.executeQuery("SELECT timestamp, latitud, longitud, velocidad, rumbo, altitud FROM datos WHERE UserId="+id.toString()+" ORDER BY timestamp DESC LIMIT 1;");
	  if(rs.last()) {
	      StringBuffer resp=new StringBuffer(rs.getTimestamp(1).toString());
	      resp.append(";");
	      resp.append(rs.getString(2));
	      resp.append(";");
	      resp.append(rs.getString(3));
	      resp.append(";");
	      resp.append(rs.getString(4));
	      resp.append(";");
	      resp.append(rs.getString(5));
	      resp.append(";");
	      resp.append(rs.getString(6));

	      cache.put(id, resp.toString());
	      out.write(resp.toString());
	  }
	  rs.close();
	  stmt.close();
	  sc.log("- Se han obtenido la posicion correctamente");
	}
	out.close();
	
      } catch (SQLException e) {
	sc.log("getPos",e);
      } catch (IOException e) {
	sc.log("getPos",e);
      }
      if(con!=null)
	connMgr.freeConnection("mysql",con);
  }

  public void showCache(HttpServletRequest request, HttpServletResponse response, Integer id) {
    try {
      PrintWriter out=new PrintWriter(response.getOutputStream());

      Map.Entry dato;
      Set datos=cache.entrySet();
      Iterator it=datos.iterator();

      while(it.hasNext()) {
	dato=(Map.Entry)it.next();
	out.write((Integer)dato.getKey());
	out.write("\t");
	out.write((String)dato.getValue());
	out.write("\n");
      }

      out.close();
    } catch(IOException e) {
      sc.log("showCache",e);
    }
  }

  public void exportEarth(HttpServletRequest request, HttpServletResponse response, Integer id) {
      String desde=request.getParameter("desde");
      String hasta=request.getParameter("hasta");	
      if(desde==null)
	desde="";
      if(hasta==null)
	hasta="";

      Timestamp desdeTs=new Timestamp(0);
      Timestamp hastaTs=new Timestamp(new java.util.Date().getTime());

      if(desde!="") {
	try {
	  desdeTs=Timestamp.valueOf(desde);
	} catch(IllegalArgumentException e) {e.printStackTrace();}
      }
      if(hasta!="") {
	try {
	  hastaTs=Timestamp.valueOf(hasta);
	} catch(IllegalArgumentException e) {e.printStackTrace();}
      }

      Connection con=null;
      try {
	response.setHeader("Cache-Control", "max-age=1, must-revalidate");
	response.setHeader("Content-Type", "application/vnd.google-earth.kml+xml .kml");
	response.setHeader("Content-disposition", "attachment; filename=Ruta_"+(desde.length()>10?desde.substring(0,10):"inicio")+"_"+(hasta.length()>10?hasta.substring(0,10):"final")+".kml");

	PrintWriter out=new PrintWriter(response.getOutputStream());
	Timestamp timestamp=null;
	sc.log("- Se va a consultar la ruta en la BBDD");
        con = connMgr.getConnection("mysql");
	PreparedStatement pstmt=null;
	if((desde=="") && (hasta=="")) {
            pstmt = con.prepareStatement("SELECT timestamp, latitud, longitud, velocidad, rumbo, altitud FROM datos WHERE UserId="+id.toString()+" ORDER BY timestamp;");
	} else {
            pstmt = con.prepareStatement("SELECT timestamp, latitud, longitud, velocidad, rumbo, altitud FROM datos WHERE UserId="+id.toString()+" AND timestamp BETWEEN ? AND ? ORDER BY timestamp;");
	    pstmt.setTimestamp(1, desdeTs);
	    pstmt.setTimestamp(2, hastaTs);
	}
	ResultSet rs=pstmt.executeQuery();
	
	float latitud, longitud, latitudNMEA, longitudNMEA;
	int grados, altitud;
	StringBuffer sb=new StringBuffer("");

	if(rs.next()) {
	latitudNMEA=rs.getInt(2)/1000000.0f;
	longitudNMEA=rs.getInt(3)/1000000.0f;
	timestamp=rs.getTimestamp(1);
	altitud=rs.getInt(6);
	grados=(int)latitudNMEA;
	latitud=(latitudNMEA-grados)/0.6f+grados;
	grados=(int)longitudNMEA;
	longitud=(longitudNMEA-grados)/0.6f+grados;

	out.write("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
	out.write("<kml xmlns=\"http://earth.google.com/kml/2.0\">");
	out.write("<NetworkLinkControl>");
	out.write("<minRefreshPeriod>30</minRefreshPeriod>");
	out.write("</NetworkLinkControl>");
	out.write("<Folder>");
	out.write("<LookAt>");
	out.write("<longitude>"+longitud+"</longitude>");
	out.write("<latitude>"+latitud+"</latitude>");
	out.write("<range>1000</range>");
	out.write("<tilt>33.01</tilt>");
	out.write("<heading>40</heading>");
	out.write("</LookAt>");
	out.write("<visibility>1</visibility>");
	out.write("<open>0</open>");
	out.write("<Placemark>");
	out.write("<name>INICIO "+timestamp.toString()+"</name>");
	out.write("<description><![CDATA[Speed Course<BR>*]]></description>");
	out.write("<Style id=\"myIcon\">");
	out.write("<IconStyle>");
	out.write("<scale>0.5</scale>");
	out.write("<color>FF0000FF</color>");
	out.write("<Icon>");
	out.write("<href>http://trackingtheworld.com.r.seekdotnet.com/dot.png</href>");
	out.write("<x>0</x>");
	out.write("<y>0</y>");
	out.write("<w>32</w>");
	out.write("<h>32</h>");
	out.write("</Icon>");
	out.write("</IconStyle>");
	out.write("</Style>");
	out.write("<Point>");
	out.write("<altitudeMode>absolute</altitudeMode>");
	out.write("<coordinates>"+longitud+","+latitud+","+altitud+"</coordinates>");
	out.write("</Point>");
	out.write("</Placemark>");

	rs.previous();
	while(rs.next()) {
	    altitud=rs.getInt(6);
	    out.write("<Placemark>");
	    timestamp=rs.getTimestamp(1);
	    out.write("<description><![CDATA["+timestamp.toString()+"<BR>Velocidad="+rs.getInt(4)/10.0f+" Rumbo="+rs.getString(5)+" Altitud="+altitud+"]]></description>");
	    out.write("<styleUrl>#myIcon</styleUrl>");
	    out.write("<Style>");
	    out.write("<IconStyle>");
	    out.write("<color>FF0075FF</color>");
	    out.write("</IconStyle>");
	    out.write("</Style>");
	    out.write("<Point>");
	    out.write("<altitudeMode>absolute</altitudeMode>");
	    latitudNMEA=rs.getInt(2)/1000000.0f;
	    longitudNMEA=rs.getInt(3)/1000000.0f;
	    grados=(int)latitudNMEA;
	    latitud=(latitudNMEA-grados)/0.6f+grados;
	    grados=(int)longitudNMEA;
	    longitud=(longitudNMEA-grados)/0.6f+grados;
	    out.write("<coordinates>"+longitud+","+latitud+","+altitud+"</coordinates>");
	    out.write("</Point>");
	    out.write("</Placemark>");

	    sb.append(longitud);
	    sb.append(",");
	    sb.append(latitud);
	    sb.append(",");
	    sb.append(altitud);
	    sb.append(" ");
	}
	out.write("<Placemark>");
	out.write("<Style>");
	out.write("<LineStyle>");
	out.write("<color>ff000000</color>");
	out.write("<width>5</width>");
	out.write("</LineStyle>");
	out.write("</Style>");
	out.write("<LineString>");
	out.write("<extrude>0</extrude>");
	out.write("<tessellate>1</tessellate>");
	out.write("<altitudeMode>absolute</altitudeMode>");
	out.write("<coordinates>");
	out.write(sb.toString());
	out.write("</coordinates>");
	out.write("</LineString>");
	out.write("</Placemark>");

	out.write("<Placemark>");
	out.write("<Style>");
	out.write("<LineStyle>");
	out.write("<color>60000000</color>");
	out.write("<width>5</width>");
	out.write("</LineStyle>");
	out.write("</Style>");
	out.write("<LineString>");
	out.write("<extrude>0</extrude>");
	out.write("<tessellate>1</tessellate>");
	out.write("<altitudeMode>clampToGround</altitudeMode>");
	out.write("<coordinates>");
	out.write(sb.toString());
	out.write("</coordinates>");
	out.write("</LineString>");
	out.write("</Placemark>");
	out.write("</Folder>");
	out.write("</kml>");
	}

	rs.close();
	pstmt.close();
	sc.log("- Se ha obtenido la ruta correctamente");

	out.close();
	
      } catch (SQLException e) {
	sc.log("getRuta",e);
      } catch (IOException e) {
	sc.log("getRuta",e);
      }
      if(con!=null)
	connMgr.freeConnection("mysql",con);
  }

  public void exportOzi(HttpServletRequest request, HttpServletResponse response, Integer id) {
      String desde=request.getParameter("desde");
      String hasta=request.getParameter("hasta");	
      if(desde==null)
	desde="";
      if(hasta==null)
	hasta="";

      Timestamp desdeTs=new Timestamp(0);
      Timestamp hastaTs=new Timestamp(new java.util.Date().getTime());

      if(desde!="") {
	try {
	  desdeTs=Timestamp.valueOf(desde);
	} catch(IllegalArgumentException e) {e.printStackTrace();}
      }
      if(hasta!="") {
	try {
	  hastaTs=Timestamp.valueOf(hasta);
	} catch(IllegalArgumentException e) {e.printStackTrace();}
      }

      Connection con=null;
      try {
	response.setHeader("Cache-Control", "max-age=1, must-revalidate");
	response.setHeader("Content-Type", "application/octet-stream");
	response.setHeader("Content-disposition", "attachment; filename=Ruta_"+(desde.length()>10?desde.substring(0,10):"inicio")+"_"+(hasta.length()>10?hasta.substring(0,10):"final")+".plt");

	PrintWriter out=new PrintWriter(response.getOutputStream());
	Timestamp timestamp=null;
	sc.log("- Se va a consultar la ruta en la BBDD");
        con = connMgr.getConnection("mysql");
	PreparedStatement pstmt=null;
	if((desde=="") && (hasta=="")) {
            pstmt = con.prepareStatement("SELECT timestamp, latitud, longitud, velocidad, rumbo, altitud FROM datos WHERE UserId="+id.toString()+" ORDER BY timestamp;");
	} else {
            pstmt = con.prepareStatement("SELECT timestamp, latitud, longitud, velocidad, rumbo, altitud FROM datos WHERE UserId="+id.toString()+" AND timestamp BETWEEN ? AND ? ORDER BY timestamp;");
	    pstmt.setTimestamp(1, desdeTs);
	    pstmt.setTimestamp(2, hastaTs);
	}
	ResultSet rs=pstmt.executeQuery();
	
	float latitud, longitud, latitudNMEA, longitudNMEA;
	int grados;
	Timestamp refTime=new Timestamp(-1,12,30, 0, 0, 0, 0);
	long fecha;
	float timeInDay;

	out.write("OziExplorer Track Point File Version 2.1\r\n");
	out.write("WGS 84\r\n");
	out.write("Altitude is in Feet\r\n");
	out.write("Reserved 3\r\n");
	out.write("0,2,255,Ruta Localizador GPS,0,0,2,8421376\r\n");
	out.write("0\r\n");
	while(rs.next()) {
	    timestamp=rs.getTimestamp(1);
	    latitudNMEA=rs.getInt(2)/1000000.0f;
	    longitudNMEA=rs.getInt(3)/1000000.0f;
	    grados=(int)latitudNMEA;
	    latitud=(latitudNMEA-grados)/0.6f+grados;
	    grados=(int)longitudNMEA;
	    longitud=(longitudNMEA-grados)/0.6f+grados;

	    fecha=(timestamp.getTime()-refTime.getTime())/86400000L;
	    timeInDay=(timestamp.getHours()*3600+timestamp.getMinutes()*60+timestamp.getSeconds())/86400.0f;
	    out.write(latitud+","+longitud+",0,"+(int)(rs.getInt(6)/0.304801)+","+fecha+Float.toString(timeInDay).substring(1)+",   ,   \r\n");
	}

	rs.close();
	pstmt.close();
	sc.log("- Se ha obtenido la ruta correctamente");

	out.close();
	
      } catch (SQLException e) {
	sc.log("getRuta",e);
      } catch (IOException e) {
	sc.log("getRuta",e);
      }
      if(con!=null)
	connMgr.freeConnection("mysql",con);
  }


  public void guardarGoogle(HttpServletRequest request, HttpServletResponse response, Integer id) {
      String desde=request.getParameter("desde");
      String hasta=request.getParameter("hasta");	
      String offline=request.getParameter("offline");	
      String map=request.getParameter("map");	

      String forward=null;

      if(desde==null)
	desde="";
      if(hasta==null)
	hasta="";

      if(offline!=null)
	forward="/jsp/GoogleGPS_offline_descargar";
      else
	forward="/jsp/GoogleGPS_recorrido_descargar";

      if(map.compareTo("GM")==0)
	forward+="_GM.jsp";
      else
	forward+="_VE.jsp";

      response.setHeader("Content-Tpye", "application/octet-stream");
      response.setHeader("Content-disposition", "attachment; filename=Ruta_"+(desde.length()>10?desde.substring(0,10):"inicio")+"_"+(hasta.length()>10?hasta.substring(0,10):"final")+".html");

      try {
      	RequestDispatcher rd=sc.getRequestDispatcher(forward);
      	rd.forward(request,response);
      } catch(Exception e) {
	e.printStackTrace();
      }
  }

  public void desconectar(HttpServletRequest request, HttpServletResponse response, Integer id) {
      sc.log("- Se va a invalidar la sesion");
      request.getSession(false).invalidate();
      try {
	response.setHeader("Cache-Control", "max-age=1, must-revalidate");
	RequestDispatcher rd=sc.getRequestDispatcher("/jsp/index.jsp");
	rd.forward(request,response);
      } catch (IOException e) {
	sc.log("desconectar",e);
      } catch (ServletException e) {
	sc.log("desconectar",e);
      }
 }

 public void nombreUsuario(HttpServletRequest request, HttpServletResponse response, Integer id) {
      String nombre=request.getParameter("nombreUsuario").trim();
      boolean existeUsuario;
      Connection con=null;

      try {
	if((nombre==null) || (nombre.length()==0)) {
		sc.log("- El nombre introducido contiene caracteres no validos: "+nombre);	
	  	Locale locale=request.getLocale();
	  	ResourceBundle bundle=ResourceBundle.getBundle("messages.messages", locale);
	  	request.setAttribute("msg", bundle.getString("msg.6"));
	  	request.setAttribute("next","/VEGPS/jsp/CambiarNombre.jsp");
	  	RequestDispatcher rd=sc.getRequestDispatcher("/jsp/msg.jsp");
	  	rd.forward(request,response);
        } else if(nombre.length()>12) {
		sc.log("- WARNING: El nombre contiene mas de 12 caracteres");
	  	Locale locale=request.getLocale();
	  	ResourceBundle bundle=ResourceBundle.getBundle("messages.messages", locale);
	  	request.setAttribute("msg", bundle.getString("msg.7"));
	  	request.setAttribute("next","/VEGPS/jsp/CambiarNombre.jsp");
	  	RequestDispatcher rd=sc.getRequestDispatcher("/jsp/msg.jsp");
	  	rd.forward(request,response);
        } else {
		sc.log("- Se va a actualizar el nombre de usuario en la BBDD: "+nombre);
		con = connMgr.getConnection("mysql");
		Statement stmt = con.createStatement();
		ResultSet rs=stmt.executeQuery("SELECT user FROM usuarios WHERE user='"+nombre+"';");
		existeUsuario=rs.next();
		if(!existeUsuario)
			stmt.executeUpdate("UPDATE usuarios SET user='"+nombre+"' WHERE id="+id+";");

		rs.close();
		stmt.close();
		connMgr.freeConnection("mysql",con);

		if(existeUsuario) {
			sc.log("- No se ha actualizado el nombre, porque ya existe");
	  		Locale locale=request.getLocale();
	  		ResourceBundle bundle=ResourceBundle.getBundle("messages.messages", locale);
	  		request.setAttribute("msg", bundle.getString("msg.8"));
	  		request.setAttribute("next","/VEGPS/jsp/CambiarNombre.jsp");
	  		RequestDispatcher rd=sc.getRequestDispatcher("/jsp/msg.jsp");
	  		rd.forward(request,response);
		} else {
			sc.log("- Se ha actualizado el nombre correctamente");
	    		RequestDispatcher rd=sc.getRequestDispatcher("/jsp/CambiarDatos.jsp");
	    		rd.forward(request,response);
		}
        }
      } catch (SQLException e) {
		if(con!=null)
		  connMgr.freeConnection("mysql",con);
		sc.log("nombreUsuario",e);
      } catch (IOException e) {
		sc.log("nombreUsuario",e);
      } catch (ServletException e) {
		sc.log("nombreUsuario",e);
      }
 }

 public void cambiarDatos(HttpServletRequest request, HttpServletResponse response, Integer id) {
      String oldPasswd=request.getParameter("oldPasswd").trim();
      String newPasswd=request.getParameter("newPasswd").trim();
      String email=request.getParameter("email").trim();
      String oldPasswdCrypt=PasswordService.getInstance().encrypt(oldPasswd);
      String newPasswdCrypt=PasswordService.getInstance().encrypt(newPasswd);
      boolean claveCorrecta=false;
      Connection con=null;

      try {
        if((oldPasswd==null) || (newPasswd==null) || (email==null)) {
		sc.log("- WARNING: faltan paramentros en cambiarDatos");
	  	Locale locale=request.getLocale();
	  	ResourceBundle bundle=ResourceBundle.getBundle("messages.messages", locale);
		request.setAttribute("msg", bundle.getString("msg.9"));
		request.setAttribute("next","/VEGPS/jsp/index.jsp");
		RequestDispatcher rd=sc.getRequestDispatcher("/jsp/msg.jsp");
		rd.forward(request,response);
        } else if((oldPasswd.length()>12) || (newPasswd.length()>12) || (email.length()>255)) {
		sc.log("- Clave mayor de 12 caracteres o direccion de correo electronico mayor de 255 caracteres");
	  	Locale locale=request.getLocale();
	  	ResourceBundle bundle=ResourceBundle.getBundle("messages.messages", locale);
		request.setAttribute("msg", bundle.getString("msg.10"));
		request.setAttribute("next","/VEGPS/jsp/CambiarDatos.jsp");
		RequestDispatcher rd=sc.getRequestDispatcher("/jsp/msg.jsp");
		rd.forward(request,response);
        } else {
	  sc.log("- Se va a cambiar la clave en la BBDD");
	  con = connMgr.getConnection("mysql");
	  PreparedStatement pstmt = con.prepareStatement("SELECT user, password FROM usuarios WHERE id="+id+";");
	  ResultSet rs=pstmt.executeQuery();
	  rs.next();
	  String usuario=rs.getString("user");
	  String passwordCrypt=rs.getString("password");
	  String digest=PasswordService.getInstance().encrypt(usuario.toLowerCase()+"\000"+newPasswd);
	  pstmt.close();
	  pstmt=con.prepareStatement("UPDATE usuarios SET user=?, password=?, digest=?, email=? WHERE id="+id+";");
	  if(oldPasswdCrypt.compareTo(passwordCrypt)==0) {
		pstmt.setString(1, usuario);
		pstmt.setString(2, newPasswdCrypt);
		pstmt.setString(3, digest);
		pstmt.setString(4, email);
		pstmt.executeUpdate();

		claveCorrecta=true;
	  }
	  rs.close();
	  pstmt.close();
	  connMgr.freeConnection("mysql",con);
	
          if(claveCorrecta) {
	    sc.log("- La clave se ha cambiado correctamente");
	    RequestDispatcher rd=sc.getRequestDispatcher("/jsp/Principal.jsp");
	    rd.forward(request,response);
	  }
          else {
	    sc.log("- La clave antigua no es correcta. Cambio no realizado.");
	    Locale locale=request.getLocale();
	    ResourceBundle bundle=ResourceBundle.getBundle("messages.messages", locale);
	    request.setAttribute("msg", bundle.getString("msg.11"));
	    request.setAttribute("next","/VEGPS/jsp/CambiarDatos.jsp");
	    RequestDispatcher rd=sc.getRequestDispatcher("/jsp/msg.jsp");
	    rd.forward(request,response);
          }
        }
      } catch (SQLException e) {
        if(con!=null)
	  connMgr.freeConnection("mysql",con);
	sc.log("cambiarClave",e);
      } catch (ServletException e) {
	sc.log("cambiarClave",e);
      } catch (IOException e) {
	sc.log("cambiarClave",e);
      }
 }

 public void recordarClave(HttpServletRequest request, HttpServletResponse response) {
      String usuario=request.getParameter("usuario");
      String email=request.getParameter("email");

      Connection con=null;
      String mailhost="127.0.0.1";

      try {
	if(usuario==null)
		usuario="";
	if(email==null)
		email="";

	if((usuario.length()==0) || (email.length()==0)) {
		sc.log("- WARNING: parametros incorrectos en recordarClave");
	  	Locale locale=request.getLocale();
	  	ResourceBundle bundle=ResourceBundle.getBundle("messages.messages", locale);
	  	request.setAttribute("msg", bundle.getString("msg.12"));
	  	request.setAttribute("next","/VEGPS/jsp/index.jsp");
		RequestDispatcher rd=sc.getRequestDispatcher("/jsp/msg.jsp");
		rd.forward(request,response);
        } else {
	  usuario=usuario.trim();
	  email=email.trim();
	  sc.log("- Se va a consultar si ya existe el usuario en la BBDD");
	  con = connMgr.getConnection("mysql");
	  PreparedStatement pstmt = con.prepareStatement("SELECT id FROM usuarios WHERE user=? AND email=?;");
	  pstmt.setString(1,usuario);
	  pstmt.setString(2,email);
	  ResultSet rs=pstmt.executeQuery();
	  if(!rs.next()) {
		rs.close();
		pstmt.close();
		sc.log("- El usuario no existe");
	  	Locale locale=request.getLocale();
	  	ResourceBundle bundle=ResourceBundle.getBundle("messages.messages", locale);
		request.setAttribute("msg", bundle.getString("msg.13").replace("{0}", usuario).replace("{1}", email));
		request.setAttribute("next","/VEGPS/jsp/index.jsp");
		RequestDispatcher rd=sc.getRequestDispatcher("/jsp/msg.jsp");
		rd.forward(request,response);
	  } else {
		int id=rs.getInt("id");
		rs.close();
		String password=generaClave(8);


                Properties props=System.getProperties();
                props.put("mail.smtp.host", mailhost);
                props.put("mail.smtp.auth", false);

                Session session=Session.getInstance(props, null);

                Message msg=new MimeMessage(session);
                msg.setFrom(new InternetAddress("contacto@gpsou.es"));
                msg.setRecipient(Message.RecipientType.TO, new InternetAddress(email));
                msg.setSubject("GPS-ou");

		Locale locale=request.getLocale();
		ResourceBundle bundle=ResourceBundle.getBundle("messages.messages", locale);
		String texto="<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n";
		texto+="<html>\n";
		texto+="<head>\n";
		texto+="  <title>GPSou</title>\n";
		texto+="  <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n";
		texto+="</head>\n";
		texto+="<body>\n";
		texto+="  <p style=\"text-align: center\"><img src=\"http://www.gpsou.es/VEGPS/html/images/GPSou-logo-banner.png\" alt=\"GPSou\"></p>\n";
		texto+="<div style=\"text-align: center\">\n";
		texto+="<table border=\"0\" width=\"530px\" cellspacing=\"0\" cellpadding=\"0\" style=\"margin-left: auto; margin-right: auto\">\n";
		texto+="<tr><td>\n";
		texto+="<p style=\"text-align: left\"><br>\n";
                texto+=bundle.getString("mail.2").replace("{0}",password);
                texto+="<a href=\"http://www.gpsou.es\">http://www.gpsou.es</a><br></p>";
                texto+="</td></tr>\n";
                texto+="</table>\n";
                texto+="</div>\n";
                texto+="</body>\n";
                texto+="</html>";

                msg.setContent(texto, "text/html");

                msg.setHeader("X-Mailer", "smtpsend");
                msg.setSentDate(new java.util.Date());

                SMTPTransport t=(SMTPTransport)session.getTransport("smtp");
                t.connect(mailhost, null, null);
//                t.connect(mailhost, userSMTP, passwdSMTP);
                t.sendMessage(msg, msg.getAllRecipients());

                t.close();



	  	String passwordCrypt=PasswordService.getInstance().encrypt(password);
	  	String digest=PasswordService.getInstance().encrypt(usuario.toLowerCase()+"\000"+password);
	  	pstmt=con.prepareStatement("UPDATE usuarios SET password=?, digest=? WHERE id="+id+";");
		pstmt.setString(1, passwordCrypt);
		pstmt.setString(2, digest);
		pstmt.executeUpdate();
	  	pstmt.close();
	    	sc.log("- La clave se ha modificado correctamente");
	        request.setAttribute("msg", bundle.getString("msg.14"));
	        request.setAttribute("next","/VEGPS/jsp/index.jsp");
	        RequestDispatcher rd=sc.getRequestDispatcher("/jsp/msg.jsp");
	        rd.forward(request,response);
	  }
	
        }
      } catch (SQLException e) {
	  sc.log("recordarClave",e);
      } catch (ServletException e) {
	sc.log("recordarClave",e);
      } catch (IOException e) {
	sc.log("recordarClave",e);
      } catch (MessagingException e) {
	sc.log("recordarClave",e);
      }
      if(con!=null)
	  connMgr.freeConnection("mysql",con);
 }

 String insertaBD(int idUser, String posiciones) {
      int nRegistros=0;
      int dupRegistros=0;
      int errRegistros=0;
      String result="ERROR";
      int latitud=0, longitud=0, velocidad=0, rumbo=0, altitud=0;
      java.sql.Timestamp timestamp=null;
      SimpleDateFormat formater=new SimpleDateFormat("ddMMyyHHmmssSSS");


      String[] pos=posiciones.split("\n");
      Connection con=null;
      PreparedStatement pstmt=null;
      
      sc.log("- Se va a insertar un grupo de registros en la BBDD.");
      con = connMgr.getConnection("mysql");
      try {
        pstmt=con.prepareStatement("INSERT INTO datos (UserId, timestamp, latitud, longitud, velocidad, rumbo, altitud) VALUES (?, ?, ?, ?, ?, ?, ?);");
      } catch(SQLException e) {
	e.printStackTrace();
      }

      for(int i=0;i<pos.length;i++) {
        String[] datos=pos[i].split(";");

	try {
            if(datos.length==6) {
                latitud=Integer.parseInt(datos[0]);
                longitud=Integer.parseInt(datos[1]);
                velocidad=Integer.parseInt(datos[2]);
                rumbo=Integer.parseInt(datos[3]);
                altitud=Integer.parseInt(datos[4]);
                timestamp=new java.sql.Timestamp(formater.parse(datos[5].trim()).getTime());

                pstmt.setInt(1, idUser);
                pstmt.setTimestamp(2, timestamp);
                pstmt.setInt(3, latitud);
                pstmt.setInt(4, longitud);
                pstmt.setInt(5, velocidad);
                pstmt.setInt(6, rumbo);
                pstmt.setInt(7, altitud);
                pstmt.executeUpdate();
		nRegistros++;
            } else {
	    	sc.log("Registro invalido A: "+pos[i]);
		errRegistros++;
	    }
        } catch (java.text.ParseException e) {
	    sc.log("Registro invalido B: "+pos[i]);
	    errRegistros++;
        } catch (SQLException e) {
	    if(e.getErrorCode()==1062) {
	    	dupRegistros++;
	    } else if(e.getErrorCode()==0) { 
		sc.log("Registro invalido C: "+pos[i]+". Error code: "+e.getMessage());
		errRegistros++;
	    }
        }
      }

      try {
        pstmt.close();
      } catch(SQLException e) {
	e.printStackTrace();
      }

      if((pos.length == nRegistros + dupRegistros + errRegistros) || (posiciones.length()==0)) {
	  result="OK";
          sc.log("Se han insertado "+nRegistros+" registros en la BBDD. " + dupRegistros + " registros duplicados. " + errRegistros + " registros erroneos. Total: " + pos.length + " registros.");
	  String posActual;
	  if(((posActual=(String)cache.get(idUser))!=null) && (timestamp!=null)) {
	    try{
		SimpleDateFormat parser=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S");
		int i=posActual.indexOf(';');
                java.sql.Timestamp t=new java.sql.Timestamp(parser.parse(posActual.substring(0, i)).getTime());
		if(timestamp.compareTo(t)>0) {
		  sc.log("Se actualiza la cache con la posicion mas reciente");
	          StringBuffer resp=new StringBuffer(timestamp.toString());
	          resp.append(";");
	          resp.append(latitud);
	          resp.append(";");
	          resp.append(longitud);
	          resp.append(";");
	          resp.append(velocidad);
	          resp.append(";");
	          resp.append(rumbo);
	          resp.append(";");
	          resp.append(altitud);

	          cache.put(idUser, resp.toString());
		}
	    } catch(java.text.ParseException e) {
		sc.log("insertaBD", e);
	    }
	  }
      } else {
	sc.log("nRegistros: "+nRegistros);
	sc.log("dupRegistros: "+dupRegistros);
	sc.log("pos.length: "+pos.length);
	sc.log("Se ha producido un error al insertar los registros en la BBDD");
      }

      if(con!=null)
        connMgr.freeConnection("mysql",con);

      return(result);
 }














 public void infoServicio(HttpServletRequest request, HttpServletResponse response, Integer id) {
      String info=request.getParameter("info");
      String palClave=request.getParameter("palClave");
      Connection con=null;

      if(info==null)
	info="";
      if(palClave==null)
	palClave="";

      try {
	if((info.length()>255) || (palClave.length()>255)){
		sc.log("- WARNING: El la descripcion del servicio o las palabras clave contienen mas de 255 caracteres.");
	  	request.setAttribute("msg", "Solo se admiten 255 caracteres como m&aacute;ximo para los campos descripci&oacute;n del servicio y palabras clave.");
	  	request.setAttribute("next","/PaginasP/jsp/Paginas.jsp");
	  	RequestDispatcher rd=sc.getRequestDispatcher(jspDir+"/msg.jsp");
	  	rd.forward(request,response);
	} else {
                sc.log("- Se va a actualizar la informacion del servicio en la BBDD.");
                con = connMgr.getConnection("mysql");
                PreparedStatement pstmt = con.prepareStatement("UPDATE usuarios SET info=?, palClave=? WHERE id="+id+";");
		pstmt.setString(1,info);
		pstmt.setString(2,palClave);
		pstmt.executeUpdate();
		pstmt.close();
                connMgr.freeConnection("mysql",con);
		sc.log("- Se ha actualizado la informacion correctamente");
	  	RequestDispatcher rd=sc.getRequestDispatcher(jspDir+"/Paginas.jsp");
	  	rd.forward(request,response);
	}
      } catch (SQLException e) {
                if(con!=null)
                  connMgr.freeConnection("mysql",con);
                sc.log("infoServicio",e);
      } catch (IOException e) {
                sc.log("infoServicio",e);
      } catch (ServletException e) {
                sc.log("infoServicio",e);
      }
 }


 public void nuevaPagina(HttpServletRequest request, HttpServletResponse response, Integer id) {
      String nombre=request.getParameter("nombre").trim();
      Connection con=null;
      try {
        if(nombre==null) {
	  sc.log("- WARNING: falta el parámetro 'nombre' en la petición");
	  request.setAttribute("msg", "Error de acceso");
	  request.setAttribute("next","/PaginasPersonales");
	    RequestDispatcher rd=sc.getRequestDispatcher(jspDir+"/msg.jsp");
	    rd.forward(request,response);
        } else if(nombre.length()>255) {
	  sc.log("- WARNING: el nombre de la página contiene más de 255 caracteres: "+nombre);
	  request.setAttribute("msg", "El nombre de la p&aacute;gina no puede contener m&aacute;s de 255 caracteres");
	  request.setAttribute("next","/PaginasP/jsp/Principal.jsp");
	    RequestDispatcher rd=sc.getRequestDispatcher(jspDir+"/msg.jsp");
	    rd.forward(request,response);
        } else {
	  sc.log("- Se va a registrar la página en la BBDD");
	  con = connMgr.getConnection("mysql");
	  Statement stmt = con.createStatement();
	  ResultSet rs=stmt.executeQuery("SELECT id FROM paginas WHERE UserId="+id+" AND nombre='"+nombre+"';");
	  if(!rs.next()) {
		stmt.executeUpdate("INSERT INTO paginas (UserId, nombre, wiki) VALUES ("+id+", '"+nombre+"', 'NUEVO WIKI');");
		rs=stmt.executeQuery("SELECT id FROM paginas WHERE UserId="+id+" AND nombre='"+nombre+"';");
		rs.next();
	  }
	  int pageId=rs.getInt("id");
	  stmt.close();
	  rs.close();
	  connMgr.freeConnection("mysql",con);
	  sc.log("- La página se ha registrado correctamente");
	  response.sendRedirect("/PaginasP/jsp/Editar.jsp?id="+pageId);
        }
      } catch (SQLException e) {
	if(con!=null)
	  connMgr.freeConnection("mysql",con);
	sc.log("nuevaPagina",e);
      } catch (IOException e) {
	sc.log("nuevaPagina",e);
      } catch (ServletException e) {
	sc.log("nuevaPagina",e);
      }
 }

 public void borrarAudio(HttpServletRequest request, HttpServletResponse response, Integer id) {
      String[] borrar=request.getParameterValues("borrar");

      File dirAudio=new File("/usr/local/apache2/htdocs/PaginasPersonales/usuarios/"+id+"/audio");
      if(borrar!=null) {
	sc.log("- Se van a borrar "+borrar.length+" ficheros de audio");
	File fichero;
	for(int i=0; i<borrar.length; i++) {
	  fichero=new File(dirAudio, borrar[i]);
	  fichero.delete();
	}
      }
      try {
        RequestDispatcher rd=sc.getRequestDispatcher(jspDir+"/Audio.jsp");
        rd.forward(request,response);
      } catch (ServletException e) {
	sc.log("borrarAudio",e);
      } catch (IOException e) {
	sc.log("borrarAudio",e);
      }
  }

 public void borrar(HttpServletRequest request, HttpServletResponse response, Integer id) {
      String[] borrar=request.getParameterValues("borrar");
      Connection con=null;

      try {
	  sc.log("- Se van a borrar las páginas marcadas de la BBDD");
          con = connMgr.getConnection("mysql");
          Statement stmt = con.createStatement();

          if(borrar!=null) {
            for(int i=0; i<borrar.length;i++) {
	      try {
		  Integer.parseInt(borrar[i]);
	    	  stmt.executeUpdate("DELETE FROM paginas WHERE UserId="+id+" AND id="+borrar[i]+";");
	      } catch (NumberFormatException e) {
		  sc.log("borrar",e);
	      }
	    }
          }
          stmt.close();
          connMgr.freeConnection("mysql",con);
	  sc.log("- Las páginas se han eliminado correctamente");
          RequestDispatcher rd=sc.getRequestDispatcher(jspDir+"/Paginas.jsp");
          rd.forward(request,response);
      } catch (SQLException e) {
	if(con!=null)
          connMgr.freeConnection("mysql",con);
	sc.log("borrar",e);
      } catch (ServletException e) {
	sc.log("borrar",e);
      } catch (IOException e) {
	sc.log("borrar",e);
      }
 }

 public void guardarWiki(HttpServletRequest request, HttpServletResponse response, Integer userId) {
      String wiki=request.getParameter("wiki");
      String pageId=request.getParameter("pageId");
      Connection con=null;
	
      try {
	Integer.parseInt(pageId);

        if((wiki==null) || (pageId==null)) {
	  sc.log("- WARNING: faltan parámentros en la petición");
	  request.setAttribute("msg", "Error de acceso");
	  request.setAttribute("next","/PaginasPersonales");
	  RequestDispatcher rd=sc.getRequestDispatcher(jspDir+"/msg.jsp");
	  rd.forward(request,response);
        } else if(wiki.length()>65535) {
	  sc.log("- WARNING: la longitud de la página es superior a 65535 caracteres"+wiki);
	  request.setAttribute("msg", "El texto no puede ocupar m&aacute;s de 65535 carateres");
	  request.setAttribute("next","/PaginasP/jsp/Principal.jsp");
	  RequestDispatcher rd=sc.getRequestDispatcher(jspDir+"/msg.jsp");
	  rd.forward(request,response);
        } else {
	  Parser parser=new Parser();
	  Vector links=new Vector();

	  sc.log("- Se va a guardar la página en la BBDD");
          con = connMgr.getConnection("mysql");
	  ResultSet rs=null;
	  PreparedStatement pstmt=con.prepareStatement("UPDATE paginas SET wiki=? WHERE id="+pageId+";");
	  pstmt.setString(1, wiki);
	  pstmt.executeUpdate();
	  pstmt.close();
	
	  parser.parse(wiki, links, userId.intValue());
	  pstmt=con.prepareStatement("SELECT * FROM paginas WHERE UserId="+userId+" AND nombre=?;");
	  PreparedStatement pstmtInsert=con.prepareStatement("INSERT INTO paginas (UserId, nombre, wiki) VALUES ("+userId+", ?, null);");
	  for(int i=0; i<links.size(); i++) {
		sc.log("- Se va a crear la página: "+links.elementAt(i));
		pstmt.setString(1,(String)links.elementAt(i));
		rs=pstmt.executeQuery();
		if(!rs.next()) {
			pstmtInsert.setString(1,(String)links.elementAt(i));
			pstmtInsert.executeUpdate();
		}
		rs.close();
	  }
		
          pstmt.close();
	  pstmtInsert.close();
          connMgr.freeConnection("mysql",con);
	  sc.log("- La página se ha guardado correctamente");

	  RequestDispatcher rd=sc.getRequestDispatcher(jspDir+"/Principal.jsp");
	  rd.forward(request,response);
        }
      } catch (ServletException e) {
	sc.log("guardarWiki",e);
      } catch (IOException e) {
	sc.log("guardarWiki",e);
      } catch (SQLException e) {
	if(con!=null)
          connMgr.freeConnection("mysql",con);
	sc.log("guardarWiki",e);
      } catch (NumberFormatException e) {
	try {
	  RequestDispatcher rd=sc.getRequestDispatcher(jspDir+"/salida.jsp");
	  rd.forward(request,response);
	} catch (IOException ex) {
	  ex.printStackTrace();
	} catch (ServletException ex) {
	  ex.printStackTrace();
	}
      }
 }


  public void principal(HttpServletRequest request, HttpServletResponse response, Integer id) {
      Connection con=null;
      try {
	String user;
	sc.log("- Se van a consultar los datos del usuario en la BBDD");
        con = connMgr.getConnection("mysql");
        Statement stmt = con.createStatement();
	ResultSet rs=stmt.executeQuery("SELECT * FROM usuarios WHERE id="+id.toString()+";");
	rs.next();
	user=rs.getString("user");
	rs.close();
	stmt.close();
	connMgr.freeConnection("mysql",con);
	sc.log("- Se han obtenido los datos de usuario correctamente");
	if(user==null) {
		sc.log("- El usuario no ha elegido un nombre todavía");
		RequestDispatcher rd=sc.getRequestDispatcher(jspDir+"/SetUser.jsp");
		rd.forward(request,response);
	} else {
		sc.log("- Entramos en la página principal");
		RequestDispatcher rd=sc.getRequestDispatcher("/jsp/Principal.jsp");
		rd.forward(request,response);
	}
      } catch (SQLException e) {
	if(con!=null)
	  connMgr.freeConnection("mysql",con);
	sc.log("principal",e);
      } catch (ServletException e) {
	sc.log("principal",e);
      } catch (IOException e) {
	sc.log("principal",e);
      }
  }

  public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
      doPost(request, response);
  }

  public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
      Class c=this.getClass();
      Class[] params={HttpServletRequest.class, HttpServletResponse.class, Integer.class};
      Method p;
      HttpSession session;
      Integer idUser;

      log(request);

      if(request.getRequestURI().indexOf("imode")!=-1)
	jspDir="/ijsp";
      else
	jspDir="/jsp";

      String proc=request.getParameter("p");

      if(proc==null)
	proc="principal";

      if(proc.compareTo("login")==0) {
        sc.log("- Login usuario");
	validar(request,response);
      } else if(proc.compareTo("nuevoUsuario")==0) {
  	nuevoUsuario(request, response); 
      } else if(proc.compareTo("recordarClave")==0) {
  	recordarClave(request, response); 
      } else if ((session=request.getSession(false))==null) {
	sc.log("- No existe sesión creada: vamos a la página de inicio");
	response.setHeader("Cache-Control", "max-age=1, must-revalidate");
	RequestDispatcher rd=sc.getRequestDispatcher("/jsp/index.jsp");
	rd.forward(request,response);
      } else if ((idUser=(Integer)session.getAttribute("id"))==null) {
	sc.log("- WARNING: no existe el parámetro 'id' en la sesión");
	response.setHeader("Cache-Control", "max-age=1, must-revalidate");
	RequestDispatcher rd=sc.getRequestDispatcher("/jsp/index.jsp");
	rd.forward(request,response);
      } else {
        Object[] arguments={request, response, idUser};
	sc.log("- Sesión existente");
       	try {
        	p=c.getMethod(proc,params);
          	try {
			sc.log("- Llamada al método: "+proc);
			p.invoke(this,arguments);
	  	} catch (IllegalAccessException e) {
			sc.log("doPost: servletPaginasPersonales",e);
	  	} catch (InvocationTargetException e) {
			sc.log("doPost: servletPaginasPersonales",e);
	  	}
        } catch (NoSuchMethodException e) {
		sc.log("- WARNING: El método no existe");
	  	Locale locale=request.getLocale();
	  	ResourceBundle bundle=ResourceBundle.getBundle("messages.messages", locale);
	  	request.setAttribute("msg", bundle.getString("msg.15"));
	  	request.setAttribute("next","/VEGPS/jsp/index.jsp");
	  	RequestDispatcher rd=sc.getRequestDispatcher(jspDir+"/msg.jsp");
	  	rd.forward(request,response);
        }
      }
  }

public static String teclas(String str) {
  String letras[]={"0","1","2abcABC","3defDEF","4ghiGHI","5jklJKL","6mnoMNO","7pqrsPQRS","8tuvTUV","9wxyzWXYZ"};
  String teclas="";
  int i,j;
  if(str==null)
	return(null);
  for(i=0;i<str.length();i++) {
        for(j=0;j<10;j++) {
                if(letras[j].indexOf(str.charAt(i))!=-1) {
                        teclas+=j;
                        break;
                }
        }
  }
  if(teclas.length()==str.length())
        return(teclas);
  else
        return(null);
}

  public String generaClave(int longitud) {
        String caracteres="abcdefghkmnprstuvwxyzABCDEFGHKMNPRSTUVWXYZ23456789";
        String clave="";

        for(int i=0;i<longitud;i++)
                clave+=caracteres.charAt((int)Math.floor(Math.random()*caracteres.length()));

        return(clave);
  }

  public void log(HttpServletRequest r) {
    String p;
                                                                                
    sc.log("---------------");
    sc.log(new java.util.Date()+" - "+r.getRemoteAddr());
    sc.log(r.getRequestURI());
                                                                                
    Enumeration e=r.getParameterNames();
    while(e.hasMoreElements()) {
      p=(String)e.nextElement();
      if(p.compareTo("datos")!=0)
        sc.log(p+" = "+r.getParameter(p));
    }
    e=r.getHeaderNames();
    while(e.hasMoreElements()) {
      p=(String)e.nextElement();
      sc.log(p+" = "+r.getHeader(p));
    }
  }

  public void init(ServletConfig config) throws ServletException {
    super.init(config);
    sc=config.getServletContext();

    if((connMgr=(DBConnectionManager)sc.getAttribute("connMgr"))==null) {
        connMgr = DBConnectionManager.getInstance();
        sc.setAttribute("connMgr", connMgr);
    }

    cache=new TreeMap();

    Thread th1=new Thread(new udpListener(cache));
    th1.start();
//    Thread th2=new Thread(new Mail(connMgr, sc));
//    th2.start();
  }

}
